home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / less-177.lha / less-177 / lsystem.c < prev    next >
C/C++ Source or Header  |  1991-04-03  |  6KB  |  306 lines

  1. /*
  2.  * Routines to execute other programs.
  3.  * Necessarily very OS dependent.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <signal.h>
  8.  
  9. #include "less.h"
  10. #include "position.h"
  11.  
  12. #if __MSDOS__
  13. #include <process.h>
  14. #include <dos.h>
  15. #include <fcntl.h>
  16. #include <io.h>
  17. #include <errno.h>
  18. #include <dir.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <ctype.h>
  23. char get_swchar();
  24. void swchar_to_dos();
  25. void swchar_to_unix();
  26. #endif
  27.  
  28. extern char *getenv();
  29.  
  30. extern int screen_trashed;
  31. extern IFILE curr_ifile;
  32.  
  33.  
  34. /*
  35.  * Pass the specified command to a shell to be executed.
  36.  * Like plain "system()", but handles resetting terminal modes, etc.
  37.  */
  38.     public void
  39. lsystem(cmd)
  40.     char *cmd;
  41. {
  42.     register int inp;
  43.     register char *shell;
  44.     register char *p;
  45.     register char *curr_filename;
  46.  
  47.     /*
  48.      * Print the command which is to be executed,
  49.      * unless the command starts with a "-".
  50.      */
  51.     if (cmd[0] == '-')
  52.         cmd++;
  53.     else
  54.     {
  55.         lower_left();
  56.         clear_eol();
  57.         putstr("!");
  58.         putstr(cmd);
  59.         putstr("\n");
  60.     }
  61.  
  62.     /*
  63.      * Close the current input file.
  64.      */
  65.     curr_filename = get_filename(curr_ifile);
  66.     (void) edit(NULL, 0);
  67.  
  68.     /*
  69.      * De-initialize the terminal and take out of raw mode.
  70.      */
  71.     deinit();
  72.     flush();    /* Make sure the deinit chars get out */
  73.     raw_mode(0);
  74.  
  75.     /*
  76.      * Restore signals to their defaults.
  77.      */
  78.     init_signals(0);
  79.  
  80.     /*
  81.      * Force standard input to be the user's terminal
  82.      * (the normal standard input), even if less's standard input 
  83.      * is coming from a pipe.
  84.      */
  85. #if __MSDOS__
  86. {
  87.     register int inp2;
  88.  
  89.     inp = dup(0);
  90.     inp2 = open("CON", O_TEXT|O_RDONLY);
  91.     dup2(0,inp2);
  92. }
  93. #else
  94.     inp = dup(0);
  95.     close(0);
  96.     if (open("/dev/tty", 0) < 0)
  97.         dup(inp);
  98. #endif
  99.  
  100.     /*
  101.      * Pass the command to the system to be executed.
  102.      * If we have a SHELL environment variable, use
  103.      * <$SHELL -c "command"> instead of just <command>.
  104.      * If the command is empty, just invoke a shell.
  105.      */
  106. #if __MSDOS__
  107. {
  108.     int result;
  109.     char sw_char;
  110.  
  111.     sw_char = get_swchar();
  112.     swchar_to_dos();
  113.     result = system(cmd);
  114.     if (result != 0)
  115.         perror("less");
  116.     if (sw_char == '-')
  117.         swchar_to_unix();
  118. }
  119. #else
  120.     p = NULL;
  121.     if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
  122.     {
  123.         if (*cmd == '\0')
  124.             p = save(shell);
  125.         else
  126.         {
  127.             p = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7, 
  128.                     sizeof(char));
  129.             sprintf(p, "%s -c \"%s\"", shell, cmd);
  130.         }
  131.     }
  132.     if (p == NULL)
  133.     {
  134.         if (*cmd == '\0')
  135.             p = save("sh");
  136.         else
  137.             p = save(cmd);
  138.     }
  139.  
  140.     system(p);
  141.     free(p);
  142. #endif
  143.  
  144.     /*
  145.      * Restore standard input, reset signals, raw mode, etc.
  146.      */
  147. #if __MSDOS__
  148.     close(inp2);
  149.     dup2(0,inp);
  150.     close(inp);
  151. #else
  152.     close(0);
  153.     dup(inp);
  154.     close(inp);
  155. #endif
  156.  
  157.     init_signals(1);
  158.     raw_mode(1);
  159.     init();
  160.     screen_trashed = 1;
  161.  
  162.     /*
  163.      * Reopen the current input file.
  164.      */
  165.     (void) edit(curr_filename, 0);
  166.  
  167. #if defined(SIGWINCH) || defined(SIGWIND)
  168.     /*
  169.      * Since we were ignoring window change signals while we executed
  170.      * the system command, we must assume the window changed.
  171.      * Warning: this leaves a signal pending (in "sigs"),
  172.      * so psignals() should be called soon after lsystem().
  173.      */
  174.     winch();
  175. #endif
  176. }
  177.  
  178. #if PIPEC
  179.  
  180. /*
  181.  * Pipe a section of the input file into the given shell command.
  182.  * The section to be piped is the section "between" the current
  183.  * position and the position marked by the given letter.
  184.  *
  185.  * The "current" position means the top line displayed if the mark
  186.  * is after the current screen, or the bottom line displayed if
  187.  * the mark is before the current screen.
  188.  * If the mark is on the current screen, the whole screen is displayed.
  189.  */
  190.     public int
  191. pipe_mark(c, cmd)
  192.     int c;
  193.     char *cmd;
  194. {
  195.     POSITION mpos, tpos, bpos;
  196.  
  197.     /*
  198.      * mpos = the marked position.
  199.      * tpos = top of screen.
  200.      * bpos = bottom of screen.
  201.      */
  202.     mpos = markpos(c);
  203.     if (mpos == NULL_POSITION)
  204.         return (-1);
  205.     tpos = position(TOP);
  206.     if (tpos == NULL_POSITION)
  207.         tpos = ch_zero();
  208.     bpos = position(BOTTOM);
  209.  
  210.      if (c == '.') 
  211.          return (pipe_data(cmd, tpos, bpos));
  212.      else if (mpos <= tpos)
  213.          return (pipe_data(cmd, mpos, tpos));
  214.      else if (bpos == NULL_POSITION)
  215.          return (pipe_data(cmd, tpos, bpos));
  216.      else
  217.          return (pipe_data(cmd, tpos, mpos));
  218. }
  219.  
  220. /*
  221.  * Create a pipe to the given shell command.
  222.  * Feed it the file contents between the positions spos and epos.
  223.  */
  224.     public int
  225. pipe_data(cmd, spos, epos)
  226.     char *cmd;
  227.     POSITION spos;
  228.     POSITION epos;
  229. {
  230.     register FILE *f;
  231.     register int c;
  232.     extern FILE *popen();
  233.  
  234.     /*
  235.      * This is structured much like lsystem().
  236.      * Since we're running a shell program, we must be careful
  237.      * to perform the necessary deinitialization before running
  238.      * the command, and reinitialization after it.
  239.      */
  240.     if (ch_seek(spos) != 0)
  241.     {
  242.         error("Cannot seek to start position", NULL_PARG);
  243.         return (-1);
  244.     }
  245.  
  246.     if ((f = popen(cmd, "w")) == NULL)
  247.     {
  248.         error("Cannot create pipe", NULL_PARG);
  249.         return (-1);
  250.     }
  251.     lower_left();
  252.     clear_eol();
  253.     putstr("!");
  254.     putstr(cmd);
  255.     putstr("\n");
  256.  
  257.     deinit();
  258.     flush();
  259.     raw_mode(0);
  260.     init_signals(0);
  261. #ifdef SIGPIPE
  262.     SIGNAL(SIGPIPE, SIG_IGN);
  263. #endif
  264.  
  265.     while (epos == NULL_POSITION || spos++ <= epos)
  266.     {
  267.         /*
  268.          * Read a character from the file and give it to the pipe.
  269.          */
  270.         c = ch_forw_get();
  271.         if (c == EOI)
  272.             break;
  273.         if (putc(c, f) == EOF)
  274.             break;
  275.     }
  276.  
  277.     /*
  278.      * Finish up the last line.
  279.      */
  280.      while (c != '\n' && c != EOI ) 
  281.      {
  282.          c = ch_forw_get();
  283.          if (c == EOI)
  284.              break;
  285.          if (putc(c, f) == EOF)
  286.              break;
  287.      }
  288.  
  289.     pclose(f);
  290.  
  291. #ifdef SIGPIPE
  292.     SIGNAL(SIGPIPE, SIG_DFL);
  293. #endif
  294.     init_signals(1);
  295.     raw_mode(1);
  296.     init();
  297.     screen_trashed = 1;
  298. #if defined(SIGWINCH) || defined(SIGWIND)
  299.     /* {{ Probably don't need this here. }} */
  300.     winch();
  301. #endif
  302.     return (0);
  303. }
  304.  
  305. #endif
  306.